package cn.kinoko.service.ai.mit;

import cn.kinoko.common.code.ErrorCodeEnum;
import cn.kinoko.common.utils.BeanHelper;
import cn.kinoko.common.utils.ExceptionUtil;
import cn.kinoko.config.ai.MITConfig;
import cn.kinoko.feign.MITApiClient;
import cn.kinoko.feign.MITWebClient;
import cn.kinoko.model.ai.mit.MITOCRResult;
import cn.kinoko.model.ai.mit.req.MITTranslateReq;
import cn.kinoko.model.ai.mit.resp.MITPrintImgResp;
import cn.kinoko.model.ai.mit.resp.MITTranslateResp;
import cn.kinoko.service.ai.AIOcrService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author kk
 */
@Slf4j
@Service
public class MITService implements AIOcrService {

    // 下次重试时间，每次增加30分钟
    public static LocalDateTime NEXT_RETRY_TIME = LocalDateTime.now();
    // 失败次数
    public static final AtomicInteger FALL_COUNT = new AtomicInteger(0);

    @Resource
    private MITApiClient mitApiClient;
    @Resource
    private MITWebClient mitWebClient;
    @Resource
    private MITConfig mitConfig;

    /**
     * 是否可用
     * @return true-可用 false-不可用
     */
    @Override
    public boolean available() {
        // 服务启用且当前时间大于下次重试时间，可以请求
        return mitConfig.isEnabled() && LocalDateTime.now().isAfter(NEXT_RETRY_TIME);
    }

    /**
     * 翻译图片
     *
     * @param imageUrl 图片地址
     * @return ocr翻译结果
     */
    @Override
    public List<MITOCRResult> ocrTranslate(String imageUrl) {
        ExceptionUtil.assertion(!available(), ErrorCodeEnum.SERVICE_ERROR_C0002);
        try {
            // 调用MIT翻译接口
            MITTranslateResp translate = mitApiClient.translate(new MITTranslateReq(imageUrl));
            // 重置失败次数
            FALL_COUNT.set(0);
            // 转换结果
            return translate.getDetails().parallelStream()
                    .map(detailsDTO -> {
                        MITOCRResult mitocrResult = BeanHelper.copyProperties(detailsDTO, MITOCRResult.class);
                        assert mitocrResult != null;
                        mitocrResult.setText(detailsDTO.getText().getOriginalText());
                        mitocrResult.setCnText(detailsDTO.getText().getChs());
                        return mitocrResult;
                    }).toList();
        } catch (Exception e) {
            handleFailure(e);
            throw new ExceptionUtil.BizException(ErrorCodeEnum.SERVICE_ERROR_C0001);
        }
    }

    /**
     * 抠除文字
     *
     * @param imageUrl 图片地址
     * @return 资源地址
     */
    public String cutoutText(String imageUrl) {
        ExceptionUtil.assertion(!available(), ErrorCodeEnum.SERVICE_ERROR_C0002);
        try {
            // 发送请求
            MITPrintImgResp resp = mitWebClient.run(imageUrl, "ctd", "none", "none");
            if (!"successful".equals(resp.getStatus())) {
                throw new ExceptionUtil.BizException(ErrorCodeEnum.SERVICE_ERROR_C0001);
            }
            // 拼接资源地址
            return mitConfig.getSourceEndpoint() + resp.getTaskId() + "/final.jpg";
        } catch (Exception e) {
            handleFailure(e);
            throw new ExceptionUtil.BizException(ErrorCodeEnum.SERVICE_ERROR_C0001);
        }
    }

    /**
     * 处理失败
     *
     * @param e 异常
     */
    private void handleFailure(Exception e) {
        log.error("[MIT] 接口调用失败", e);
        // 服务失败次数超过3次，阻止请求，锁定30分钟
        if (FALL_COUNT.getAndIncrement() >= 3) {
            NEXT_RETRY_TIME = LocalDateTime.now().plusMinutes(30);
            log.error("[MIT] 服务接口调用失败3次，阻止请求，下次重试时间：{}", NEXT_RETRY_TIME);
        }
    }

}
